<?php
namespace app\api\service;

use app\Response;
use think\facade\Config;
use think\facade\Cache;
use app\common\model\UserAmount;
use app\common\model\User;

class WechatService
{

    public static function wxLogin($code){
        $data = self::getOpenId($code);
        if(!$data){
            return Response::wrapError(0,"授权登录异常!");
        }
        $userInfo = User::userInfo(["open_id"=>$data["openid"]]);
        if($userInfo&&isset($userInfo["uid"])){
            $up_data = [
                'lasttime' => time(),
            ];
            User::userEdit(["uid"=>$userInfo["uid"]],$up_data);
            if(!empty($userInfo["phone"])){//判断是否已绑定手机号
                $token = LoginService::setMyToken($userInfo["uid"]);
                $res = ["token"=>$token,"open_id"=>$data["openid"],"is_bind_phone"=>1];
            }else{
                $res = ["token"=>"","open_id"=>$data["openid"],"is_bind_phone"=>0];
            }
        }else{
            $res = ["token"=>"","open_id"=>$data["openid"],"is_bind_phone"=>0];
        }
        return Response::wrapData($res);
    }

    //微信授权注册手机号
    public static function wxRegisterService($code,$openid,$extension){
        $appId = Config::get("app.wx_xcx_AppID");
        $appSecret = Config::get("app.wx_xcx_AppSecret");
        $phone_info = self::getWxPhoneNumber($code,$appId,$appSecret);
        if(!empty($phone_info)){//获取到手机号信息,进入判断！
            $uInfo = User::userInfo(["open_id"=>$openid]);
            $phone = $phone_info["purePhoneNumber"];
            $userInfo = User::userInfo(["phone"=>$phone]);
            if(!empty($userInfo)){//查询手机号是否存在记录
                if(!empty($userInfo["open_id"])){//查询手机号是否绑定微信
                    if($userInfo["open_id"] != $openid){//查询手机号绑定微信与当前请求微信是否同一个
                        return Response::wrapError(0,"该手机号已绑定其他微信");
                    }
                }else{
                    if(empty($uInfo["phone"])){//判断当前请求微信是否可以绑定手机号
                        User::userEdit(["uid"=>$uInfo["uid"]],["open_id"=>$openid."废","enable"=>0]);
                        User::userEdit(["uid"=>$userInfo["uid"]],['lasttime' => time(),"open_id"=>$openid]);
                    }else{
                        if($uInfo["phone"] != $phone){
                            return Response::wrapError(0,"当前微信已绑定其他手机号!");
                        }
                    }
                }
                $token = LoginService::setMyToken($userInfo["uid"]);
                $res = ["token"=>$token,"is_bind_phone"=>1];
            }else{//当前手机号无注册记录
                if(empty($uInfo)){//当前微信号无注册记录 生成新用户
                    if(!empty($extension)){
                        $superorUser = User::userInfoRaw("extension = binary '$extension'"); //邀请码采用二进制 区分大小写
                        if($superorUser['uid'] <= 0){
                            return Response::wrapError("邀请码不存在");
                        }
                        if($superorUser['type'] == 21){ //代理邀请
                            $spread = '代理邀请';
                        }elseif($superorUser['type'] == 22){//商家与傲晴
                            $spread = '用户邀请';
                        }elseif($superorUser['type'] == 23){
                            $spread = '达人邀请';
                        }else{
                            $spread = '未知身份邀请';
                        }
                        $channel = $superorUser['phone'];
                    }else{
                        $superorUser['username'] = '';
                        $superorUser['uid'] = 0;
                        $spread = "";
                        $channel = "";
                    }
                    $encryption = self::createNonceStr(4);
                    $up_data = [
                        'open_id' => $openid,
                        'type' => 23,
                        'nickname' => substr_replace($phone, '****', 3, 4),
                        'superor_id' => $superorUser["uid"],
                        'extension' => UserService::extensionCreat(),//
                        'spread' => $spread,
                        'channel' => $channel,
                        'addtime' => time(),
                        'username' => $phone,
                        'phone' => $phone,
                        'encryption' => $encryption
                    ];

                    $uid = User::registered($up_data);
                    UserAmount::userAmountAdd($uid);
                    $token = LoginService::setMyToken($userInfo["uid"]);
                    $res = ["token"=>$token,"is_bind_phone"=>1];
                }else{//当前微信号有注册记录 且手机号未绑定,绑定手机号至微信号记录上
                    $up_data = ['lasttime' => time(),"phone"=>$phone];
                    User::userEdit(["uid"=>$uInfo["uid"]],$up_data);
                    $token = LoginService::setMyToken($userInfo["uid"]);
                    $res = ["token"=>$token,"is_bind_phone"=>1];
                }
            }
            return Response::wrapData($res);
        }else{
            return Response::wrapError(0,"手机号授权失败,情稍后重试!");
        }
    }


    public static function bindOpenIdService($user_id,$code){
        $data = self::getOpenId($code);
        if(!$data){
            return Response::wrapError(0,"授权登录异常!");
        }
        $userInfo = User::userInfo(["open_id"=>$data["openid"]]);
        if(!empty($userInfo)&&$userInfo["uid"]==$user_id){
            return Response::wrapData();
        }elseif(!empty($userInfo)&&!empty($userInfo["phone"])){
            return Response::wrapError(0,"当前微信已绑定其他手机号!");
        }else{
            if(!empty($userInfo)){
                User::userEdit(["uid"=>$userInfo["uid"]],["open_id"=>$userInfo["open_id"]."废","enable"=>0]);
                $res = User::userEdit(["uid"=>$user_id],['lasttime' => time(),"open_id"=>$data["openid"]]);
                if($res){
                    return Response::wrapData();
                }
            }else{
                $res = User::userEdit(["uid"=>$user_id],['lasttime' => time(),"open_id"=>$data["openid"]]);
                if($res){
                    return Response::wrapData();
                }
            }
        }
        return Response::wrapError(0,"操作失败!");
    }

    /**
     * 获取openid
     * @param $code
     * @return array
     */
    public static function getOpenId($code)
    {
        $info = self::getUnionData($code);
        if(!$info){
            return $info;
        }
        return [
            'openid' => $info["openid"],
            'session_key' => $info["session_key"]
        ];
    }




    /**
     * 获取手机号 和 access_token
     * @return array
     */
    public static function getWxPhoneNumber($code, $appid, $secret)
    {
        $token = self::getWxToken($appid, $secret);
        $url = 'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=' . $token;

        $data = json_encode(["code" => $code]);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POST, true);        // 发送post请求
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // 传入post参数

        $res = curl_exec($ch);
        curl_close($ch);
        $res = json_decode($res,true);
        if(isset($res)&&!empty($res)){
            if($res["errcode"] == 0){
                $phone_info = $res['phone_info'];
                return $phone_info;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }


    /**
     * 获取小程序用户的 open_id & token | union_id
     * @param $code string 前端提供的
     * @return bool|string
     */
    public static function getUnionData($code)
    {
        $appId = Config::get("app.wx_xcx_AppID");
        $appSecret = Config::get("app.wx_xcx_AppSecret");
        $api = 'https://api.weixin.qq.com/sns/jscode2session?appid=' . $appId . '&secret=' . $appSecret . '&js_code=' . $code . '&grant_type=authorization_code';
        $re = file_get_contents($api);
        if ($re){
            $res = json_decode($re, 1);
            if(isset($res["openid"])){
                return $res;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

    /**
     * 解密用户信息
     * @param $encrypted_data
     * @param $iv
     * @param $session_key
     * @return mixed
     * @throws CommonException
     */
    private static function userInfoDecode($encrypted_data, $iv, $session_key)
    {
        $data = base64_decode($encrypted_data);
        $iv = base64_decode($iv);
        $key = base64_decode($session_key);

        $re = openssl_decrypt($data, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
        return $re;
    }

    /**
     * 生成随机字符串
     * @param int $length
     * @return string
     */
    public static function createNonceStr($length = 16) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    public static function getWxToken($appid, $secret)
    {
        if(Cache::has("access_token")&&!empty(Cache::get("access_token"))){
            $tokenCache = Cache::get("access_token");
            return $tokenCache;
        }else{
            Cache::delete("access_token");
        }
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $secret;
        $token = json_decode(file_get_contents($url, true), true);
        $token = $token['access_token'];
        Cache::set("access_token",$token,3600);
        return $token;
    }
}